﻿using System;
using System.ComponentModel;
using System.Collections;
using System.Drawing;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace MyLibrary.UI
{
    /// <summary>
    /// 限制输入IP地址的文本框
    /// </summary>
    [DefaultProperty("IPVersion"),DefaultEvent("Resize")]
    public class IPTextBox : Panel
    {
        public enum IPVersion
        {
            IPV4 = 4,
            IPV6 = 8
        }

        private Container components = null;
        private int _sectLen;
        private int _sectHeight;
        private int _minLen;

        private IPVersion _ipv = IPVersion.IPV4;
        private IPSection[] _ipSectionArray;
        private IPSection _currentSection;

        private const int _firstMin = 1; //第一个输入框的最小值
        private const int _firstMax = 223;   //第一个输入框的最大值
        private const int _otherMin = 0; //其他输入框的最小值
        private const int _otherMax = 255;   //其他输入框的最大值

        internal IPSection CurrentSection
        {
            get { return _currentSection; }
            set { _currentSection = value; }
        }

        /// <summary>
        /// 设定IP的类型
        /// </summary>
        [Category("Design"),Editor(typeof(IPVersion),typeof(Enum)),Browsable(true)]
        public IPVersion Version
        {
            get { return this._ipv; }
            set { this._ipv = value; }
        }

        public IPTextBox()
        {
            InitializeComponent();
            InitStyle();
            InitControl();
        }

        private void InitStyle()
        {
            this.BackColor = Color.White;
            this.BorderStyle = BorderStyle.Fixed3D;
            this.Height = 23;
            this.Width = 100;
            this._minLen = 30 + (IPSection.IPSectionWidth + 1) * (int)this._ipv;
            if (this._minLen > this.Width)
                this.Width = this._minLen;
            this.Resize += new EventHandler(IPTextBox_Resize);
        }

        void IPTextBox_Resize(object sender, EventArgs e)
        {
            if (this._minLen > this.Width)
                this.Width = this._minLen;
            this.InitControl();
        }

        private void InitializeComponent() { }

        private void InitControl()
        {
            this.SuspendLayout();
            this.Controls.Clear();

            this._sectHeight = IPSection.IPSectionHeight;
            this._sectLen = (this.Width - 10) / (int)_ipv;

            //绘制输入框
            this._ipSectionArray = new IPSection[(int)this._ipv];
            Point point;
            IPSection ipSection;
            int index = 5;
            for (int i = 0; i < (int)this._ipv; i++)
            {
                ipSection = new IPSection();
                ipSection.Name = "section_" + (i + 1);
                this._ipSectionArray[i] = ipSection;
                point = new Point((this._sectLen - ipSection.Width) / 2 + index, (this.Height - ipSection.Height) / 2);
                ipSection.Location = point;
                this.Controls.Add(ipSection);
                index += this._sectLen;
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.components != null)
                    this.components.Dispose();
            }
            base.Dispose(disposing);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            //绘制IP间的"."
            int loc = 5;
            for (int i = 0; i < (int)this._ipv - 1; i++)
            {
                loc += this._sectLen;
                e.Graphics.DrawRectangle(Pens.Black, loc, (this.Height - this._sectHeight) / 2 + this._sectHeight - 5, 1, 1);
            }
        }

        /// <summary>
        /// 验证IP输入的有效性
        /// </summary>
        public static bool ValidateIPSection(object sender)
        {
            if (!(sender is IPSection))
                throw new ArgumentException("方法只能用于验证IPSection的输入");
            string text = ((IPSection)sender).Text;
            if (String.IsNullOrEmpty(text)) return false;

            int ip = Convert.ToInt32(text);
            //如果是第一个输入框
            if (((IPSection)sender).Name == ((IPTextBox)((IPSection)sender).Parent)._ipSectionArray[0].Name)
            {
                if (ip < _firstMin || ip > _firstMax)
                {
                    ((IPSection)sender).Text = _firstMax.ToString();
                    MessageBox.Show("IP地址必须在" + _firstMin + "到" + _firstMax + "之间");
                    return false;
                }
            }
            else
            {
                if (ip < _otherMin || ip > _otherMax)
                {
                    ((IPSection)sender).Text = _otherMax.ToString();
                    MessageBox.Show("IP地址必须在" + _otherMin + "到" + _otherMax + "之间");
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 定位到下一个输入框
        /// </summary>
        internal void GoToNextSection()
        {
            //如果当期的输入框为空,定位到第一个输入框
            if (this._currentSection == null)
            {
                this._ipSectionArray[0].Focus();
                return;
            }
            for (int i = 0; i < this._ipSectionArray.Length; i++)
            {
                if (this._ipSectionArray[i].Name.Equals(this._currentSection.Name))
                {
                    //如果是最后一个输入框
                    if (i == this._ipSectionArray.Length - 1)
                    {
                        this._ipSectionArray[i].Focus();
                    }
                    //定位到下一个输入框
                    else
                    {
                        this._ipSectionArray[i + 1].Focus();
                        this._ipSectionArray[i + 1].SelectionStart = 0;
                    }
                    break;
                }
            }
        }

        /// <summary>
        ///  定位到上一个输入框
        /// </summary>
        internal void GoToPreviousSection()
        {
            if (this._currentSection == null)
            {
                this._ipSectionArray[0].Focus();
                return;
            }

            for (int i = 0; i < this._ipSectionArray.Length; i++)
            {
                if (this._ipSectionArray[i].Name.Equals(this._currentSection.Name))
                {
                    //如果当前焦点在第一个输入框
                    if (i == 0)
                    {
                        this._ipSectionArray[i].Focus();
                        this._ipSectionArray[i].SelectionStart = 0;
                    }
                    else
                    {
                        this._ipSectionArray[i - 1].Focus();
                        this._ipSectionArray[i - 1].SelectionStart = 0;
                    }
                    break;
                }
            }
        }
    }

    /// <summary>
    /// IP输入框
    /// </summary>
    internal sealed class IPSection : TextBox
    {
        private Container components = null;
        private static int _width = 30;
        private static int _height = 21;

        public static int IPSectionWidth
        {
            get { return IPSection._width; }
        }

        public static int IPSectionHeight
        {
            get { return IPSection._height; }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        internal IPSection()
        {
            InitializeComponent();
            InitSection();
        }

        /// <summary>
        /// 初始化输入框属性
        /// </summary>
        private void InitSection()
        {
            this.SuspendLayout();
            this.BorderStyle = BorderStyle.None;
            this.BackColor = Color.White;
            this.TextAlign = HorizontalAlignment.Center;
            this.Width = _width;
            this.Height = _height;
            this.MaxLength = 3;
            this.ResumeLayout(false);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.components != null)
                    components.Dispose();
            }
            base.Dispose(disposing);
        }

        private void InitializeComponent()
        {
            this.KeyUp += new KeyEventHandler(IPSection_KeyUp);
            this.Enter += new EventHandler(IPSection_Enter);
        }


        /// <summary>
        /// 当焦点进入输入框时
        /// </summary>
        void IPSection_Enter(object sender, EventArgs e)
        {
            ((IPTextBox)this.Parent).CurrentSection = this;
        }

        /// <summary>
        /// 当在输入框中按键时
        /// </summary>
        void IPSection_KeyUp(object sender, KeyEventArgs e)
        {
            int key = e.KeyValue;
            //当按下".",向右箭头,向下箭头时
            if (key== 110 || key == 190 || (key == 39 || key == 40) && (this.SelectionStart == this.Text.Length))
            {
                if (this.Text.Length != 3)
                {
                    ((IPTextBox)this.Parent).GoToNextSection();
                    if(key == 110 || key == 190)
                        ((IPTextBox)this.Parent).CurrentSection.SelectAll();
                    return;
                }
            }
            //当按方向左键,方向上键
            if ((key == 37 || key == 38) && this.SelectionStart == 0)
            {
                ((IPTextBox)this.Parent).GoToPreviousSection();
                return;
            }
            //如果输入的长度达到3,则跳向下一个控件
            if (this.Text.Length == 3)
            {
                if (!IPTextBox.ValidateIPSection(this))
                {
                    this.Focus();
                    return;
                }
                if (this.SelectionStart == this.Text.Length)
                {
                    ((IPTextBox)this.Parent).GoToNextSection();
                    ((IPTextBox)this.Parent).CurrentSection.SelectAll();
                }
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
        }

        /// <summary>
        /// 重新控件的KeyPress事件,让控件对部分键的输入进行响应
        /// </summary>
        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            base.OnKeyPress(e);
            int keyValue = e.KeyChar;
            //当按键为0~9 上下左右箭头 和 空格时进行响应
            if (!(keyValue == (char)8 || (keyValue >= (char)37 && keyValue <= (char)40) || (keyValue >= (char)48 && keyValue <= (char)57)))
                e.Handled = true;
        }
    }
}
